package com.laolang.thresh.module.auth.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.laolang.thresh.framework.common.core.exception.BusinessException;
import com.laolang.thresh.module.auth.consts.AuthConsts;
import com.laolang.thresh.module.auth.domain.LoginUser;
import java.util.Objects;
import java.util.Set;
import lombok.experimental.UtilityClass;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;

/**
 * spring security 工具类.
 *
 * @author laolang
 * @version 0.1
 */
@UtilityClass
public class SecurityUtil {

    public static Long getTenantId() {
        try {
            return getLoginUser().getSysUser().getTenantId();
        } catch (Exception e) {
            throw new BusinessException("00101003", "获取用户信息异常");
        }
    }

    public static Long getLoginId() {
        try {
            return getLoginUser().getSysUser().getId();
        } catch (Exception e) {
            throw new BusinessException("00101003", "获取用户信息异常");
        }
    }

    public static LoginUser getLoginUser() {
        try {
            return (LoginUser) getAuthentication().getPrincipal();
        } catch (Exception e) {
            throw new BusinessException("00101003", "获取用户信息异常");
        }
    }

    public static Authentication getAuthentication() {
        return SecurityContextHolder.getContext().getAuthentication();
    }

    public static boolean isSuperAdmin() {
        return Objects.equals(getLoginId(), AuthConsts.SUPER_ADMIN_USER_ID);
    }

    /**
     * 是否具备某权限.
     */
    public boolean hasPerm(String permission) {
        if (StrUtil.isBlank(permission)) {
            return false;
        }
        LoginUser loginUser = SecurityUtil.getLoginUser();
        if (Objects.isNull(loginUser) || CollUtil.isEmpty(loginUser.getPerms())) {
            return false;
        }
        return hasPermissions(loginUser.getPerms(), permission);
    }

    /**
     * 是否不具备某权限.
     */
    public boolean lackPerm(String permission) {
        return !hasPerm(permission);
    }

    /**
     * 是否具备任一权限.
     */
    public boolean hasAnyPerm(String permissions) {
        if (StrUtil.isBlank(permissions)) {
            return false;
        }
        LoginUser loginUser = SecurityUtil.getLoginUser();
        if (Objects.isNull(loginUser) || CollUtil.isEmpty(loginUser.getPerms())) {
            return false;
        }
        Set<String> perms = loginUser.getPerms();
        for (String perm : permissions.split(AuthConsts.PERMISSION_DELIMETER)) {
            if (StrUtil.isNotBlank(perm) && hasPermissions(perms, perm)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 是否具备某角色.
     */
    public boolean hasRole(String role) {
        if (StrUtil.isBlank(role)) {
            return false;
        }
        LoginUser loginUser = SecurityUtil.getLoginUser();
        if (Objects.isNull(loginUser) || CollUtil.isEmpty(loginUser.getRoles())) {
            return false;
        }
        for (String userRole : loginUser.getRoles()) {
            if (StrUtil.equals(AuthConsts.SUPER_ADMIN_ROLE_NAME, userRole) || StrUtil.equals(role, userRole)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 是否不具备某角色.
     */
    public boolean blackRole(String role) {
        return !hasRole(role);
    }

    /**
     * 是否具备任一角色.
     */
    public boolean hasAnyRole(String roles) {
        if (StrUtil.isBlank(roles)) {
            return false;
        }
        LoginUser loginUser = SecurityUtil.getLoginUser();
        if (Objects.isNull(loginUser) || CollUtil.isEmpty(loginUser.getRoles())) {
            return false;
        }
        for (String role : roles.split(AuthConsts.PERMISSION_DELIMETER)) {
            if (hasRole(role)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断是否包含权限.
     */
    private boolean hasPermissions(Set<String> permissionList, String permission) {
        return permissionList.contains(AuthConsts.ALL_PERMISSION) || permissionList.contains(
            StringUtils.trim(permission));
    }
}
